package com.cskaoyan.service.coupon.wx;

import com.cskaoyan.bean.*;
import com.cskaoyan.bean.coupon.ExchangeCouponVO;
import com.cskaoyan.bean.coupon.ReceiveCouponVO;
import com.cskaoyan.mapper.CouponMapper;
import com.cskaoyan.mapper.CouponUserMapper;
import com.cskaoyan.mapper.UserMapper;
import com.cskaoyan.tool.CouponTool;
import com.cskaoyan.tool.FinalVariable;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.cskaoyan.bean.coupon.wx.ListData;

import java.util.*;

@Service
public class CouponService2Impl implements CouponService2 {

    @Autowired
    CouponMapper couponMapper;
    @Autowired
    CouponUserMapper couponUserMapper;
    @Autowired
    UserMapper userMapper;

    /**
     * 展示已领取的优惠券
     *
     * 另：两种优惠券的可用时间应该从coupon_user表中查询，不能从coupon表中查询
     * @param userId
     * @param status
     * @param page
     * @param size
     * @return
     */
    @Override
    public ListData<Coupon> myCoupons(Integer userId, String status, String page, String size) {
        List<CouponUser> couponUserList = getCouponUserList(userId, status, page, size);
        List<Coupon> coupons = getCoupons(couponUserList);

        ListData<Coupon> listData = new ListData<>();
        listData.setData(coupons);

        PageInfo<Coupon> pageInfo = new PageInfo<>(coupons);
        long total = pageInfo.getTotal();
        listData.setCount((int) total);
        return listData;
    }
//TODO
    @Override
    public List<Coupon> myCoupons(Integer userId, int status) {
        List<CouponUser> couponUserList = getCouponUserList(userId, String.valueOf(status));
        List<Coupon> coupons = getCoupons(couponUserList);

        Collections.sort(coupons, new Comparator<Coupon>() {
            @Override
            public int compare(Coupon o1, Coupon o2) {
                return o2.getDiscount().intValue() - o1.getDiscount().intValue();
            }
        });
        return coupons;
    }


    @Override
    public ExchangeCouponVO exchange(Integer userId, String code) {
        CouponExample couponExample = new CouponExample();
        CouponExample.Criteria criteria = couponExample.createCriteria();
        if (code != null){
            criteria.andCodeEqualTo(code);
        }
        List<Coupon> coupons = couponMapper.selectByExample(couponExample);

        if (coupons == null || coupons.size() == 0 || coupons.get(0).getType() != 2){
            return ExchangeCouponVO.err();
        }else {
            assert coupons.size() == 1;
            ReceiveCouponVO receiveCouponVO = checkLimitAndTotal(userId, coupons.get(0).getId(), coupons.get(0));
            if (receiveCouponVO != null){
                return ExchangeCouponVO.err("兑换码已经领取");
            }
            boolean insertIntoCouponUserTable = insertIntoCouponUserTable(userId, coupons);
            boolean updateCoupon = updateCoupon(coupons);
            if (insertIntoCouponUserTable && updateCoupon){
                return ExchangeCouponVO.ok();
            }else {
                return ExchangeCouponVO.err("未知错误不能领取，请重新登陆");
            }
        }
    }




    @Override
    public ReceiveCouponVO receive(Integer userId, Integer couponId) {
        Coupon coupon = couponMapper.selectByPrimaryKey(couponId);
        if (coupon.getType() != 0){
            return ReceiveCouponVO.error("凭借兑换码领取");
        }

        if (CouponTool.couponTimeCheck(coupon)) return ReceiveCouponVO.error("优惠券已经过期");

        ReceiveCouponVO x = checkLimitAndTotal(userId, couponId, coupon);
        if (x != null) return x;

        boolean insertCouponUser = insertCouponUser(userId, coupon);
        boolean updateCoupon = updateCoupon(coupon);

        if (insertCouponUser && updateCoupon){
            return ReceiveCouponVO.ok();
        }
        return ReceiveCouponVO.error("未知错误不能领取优惠券，请重试");
    }


    /**
     *
     * 首页展示优惠券
     * 另：过期不显示
     * 另：需要根据timetype来选显示天数还是starttime endtime？根本不需要，前端会自己识别timetype
     *
     * @param page
     * @param size
     * @return
     */
    @Override
    public ListData<Coupon> list(Integer page, Integer size) {
        PageHelper.startPage(page,size);
        CouponExample couponExample = new CouponExample();
        CouponExample.Criteria criteria = couponExample.createCriteria();
        criteria.andTypeEqualTo((short)0);
        criteria.andDeletedEqualTo(false);
        criteria.andStatusEqualTo((short) 0);
        List<Coupon> coupons = couponMapper.selectByExample(couponExample);

        ListData<Coupon> listData = new ListData<>();
        listData.setData(coupons);
        listData.setCount((int) new PageInfo<Coupon>(coupons).getTotal());
        return listData;
    }

    @Override
    public List<Coupon> selectList(Integer userId, Integer cartId, Integer grouponRulesId) {
        CouponUserExample couponUserExample = new CouponUserExample();
        CouponUserExample.Criteria criteria = couponUserExample.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andStatusEqualTo(Short.valueOf("0"));
        criteria.andStartTimeLessThan(new Date());
        criteria.andEndTimeGreaterThan(new Date());
        List<CouponUser> couponUsers = couponUserMapper.selectByExample(couponUserExample);
        List<Coupon> coupons = new LinkedList<>();
        for (CouponUser couponUser : couponUsers) {
            Integer couponId = couponUser.getCouponId();
            Coupon coupon = couponMapper.selectByPrimaryKey(couponId);
            coupon.setStartTime(couponUser.getStartTime());
            coupon.setEndTime(couponUser.getEndTime());
            coupons.add(coupon);
        }
        return coupons;
    }


    /**
     * 检查用户来领取数量是否超过limit
     * 检查优惠券总数是否大于0
     * @param userId
     * @param couponId
     * @param coupon
     * @return
     */
    private ReceiveCouponVO checkLimitAndTotal(Integer userId, Integer couponId, Coupon coupon) {
        Integer total = coupon.getTotal();
        if (total <= 0){
            return ReceiveCouponVO.error("优惠券已领完");
        }
        Short limit = coupon.getLimit();
        // 从coupon_user表中根据userId和couponId查询此用户已经领取了几张此优惠券，如果>=limit，则返回false
        CouponUserExample couponUserExample = new CouponUserExample();
        CouponUserExample.Criteria criteria = couponUserExample.createCriteria();
        if (userId != null){
            criteria.andUserIdEqualTo(userId);
        }
        if (couponId != null){
            criteria.andCouponIdEqualTo(Integer.valueOf(couponId));
        }
        List<CouponUser> list = couponUserMapper.selectByExample(couponUserExample);

        if (list.size() >= limit){
            return ReceiveCouponVO.error("优惠券已经领取");
        }
        return null;
    }

    /**
     * 更新Coupon表，优惠券总数 - 1
     * @param coupon
     * @return
     */
    private boolean updateCoupon(Coupon coupon) {
        coupon.setTotal(coupon.getTotal() - 1);
        return 1 == couponMapper.updateByPrimaryKeySelective(coupon);
    }

    /**
     * 将用户领取的优惠券信息插入到coupon_user表中
     * @param userId
     * @param coupon
     * @return
     */
    private boolean insertCouponUser(Integer userId, Coupon coupon) {
        CouponUser couponUser = new CouponUser();
        couponUser.setUserId(userId);
        couponUser.setCouponId(coupon.getId());
        couponUser.setStatus(coupon.getStatus());
        couponUser.setUsedTime(null);
        Date lastUpdateTime = coupon.getUpdateTime() == null ? coupon.getAddTime() : coupon.getUpdateTime();
        if (coupon.getTimeType() == 0){
            Date now = new Date();
            couponUser.setStartTime(now);
            couponUser.setEndTime(new Date(now.getTime() + coupon.getDays() * FinalVariable.millisecondOfDay));
        }else if (coupon.getTimeType() == 1){
            couponUser.setStartTime(coupon.getStartTime());
            couponUser.setEndTime(coupon.getEndTime());
        }

        couponUser.setOrderId(null);
        couponUser.setAddTime(new Date());
        couponUser.setUpdateTime(new Date());
        couponUser.setDeleted(coupon.getDeleted());

        return  1 == couponUserMapper.insertSelective(couponUser);
    }

    /**
     * 根据参数选择该用户的所有优惠券。
     *
     * 另：如果优惠券id重复，按照不同优惠券处理。
     * 另：优惠券显示的可用时间应该是从coupon_user查询出来的，不是coupon表中的时间
     * @param couponUserList
     * @return
     */
    private List<Coupon> getCoupons(List<CouponUser> couponUserList) {
        List<Coupon> coupons = new LinkedList<>();
        for (CouponUser couponUser : couponUserList) {
            Coupon coupon = couponMapper.selectByPrimaryKey(couponUser.getCouponId());
            coupon.setStatus(couponUser.getStatus());
            coupon.setStartTime(couponUser.getStartTime());
            coupon.setEndTime(couponUser.getEndTime());
            coupon.setDeleted(couponUser.getDeleted());
            coupon.setUpdateTime(couponUser.getUpdateTime());
            coupon.setAddTime(couponUser.getAddTime());
            coupons.add(coupon);
        }
        return coupons;
    }

    /**
     * 根据参数获得该用户某个status的所有优惠券列表
     * @param userId
     * @param status
     * @param page
     * @param size
     * @return
     */
    private List<CouponUser> getCouponUserList(Integer userId, String status, String page, String size) {
        PageHelper.startPage(Integer.valueOf(page),Integer.valueOf(size));
        CouponUserExample couponUserExample = new CouponUserExample();
        CouponUserExample.Criteria criteria = couponUserExample.createCriteria();
        if (status != null){
            criteria.andStatusEqualTo(Short.valueOf(status));
        }
        if (userId != null){
            criteria.andUserIdEqualTo(userId);
        }
        return couponUserMapper.selectByExample(couponUserExample);
    }

    private List<CouponUser> getCouponUserList(Integer userId, String status) {
        CouponUserExample couponUserExample = new CouponUserExample();
        CouponUserExample.Criteria criteria = couponUserExample.createCriteria();
        if (status != null){
            criteria.andStatusEqualTo(Short.valueOf(status));
        }
        if (userId != null){
            criteria.andUserIdEqualTo(userId);
        }
        return couponUserMapper.selectByExample(couponUserExample);
    }

    private boolean updateCoupon(List<Coupon> coupons) {
        coupons.get(0).setTotal(coupons.get(0).getTotal() - 1);
        int i = couponMapper.updateByPrimaryKeySelective(coupons.get(0));
        return 1 == i;
    }

    private boolean insertIntoCouponUserTable(Integer userId, List<Coupon> coupons) {
        Coupon coupon = coupons.get(0);
        CouponUser couponUser = new CouponUser();
        couponUser.setUserId(userId);
        couponUser.setCouponId(coupon.getId());
        couponUser.setStatus(coupon.getStatus());
        Short timeType = coupon.getTimeType();
        if (timeType == 0){
            Date now = new Date();
            couponUser.setStartTime(now);
            couponUser.setEndTime(new Date(now.getTime() + coupon.getDays() * FinalVariable.millisecondOfDay));
        }else if (timeType == 1){
            couponUser.setStartTime(coupon.getStartTime());
            couponUser.setEndTime(coupon.getEndTime());
        }
        couponUser.setAddTime(new Date());
        couponUser.setUpdateTime(new Date());
        return 1 == couponUserMapper.insertSelective(couponUser);
    }

}
